#pragma once
#include"Log.hpp"
#include"Channel.hpp"
#include<sys/timerfd.h>
#include<functional>
#include<vector>
#include<unordered_map>
#include<memory>
// #include<unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std:function<void()>;

class TimerTask(){
private:
    uint64_t _id;       //定时器任务对象ID
    uint32_t _timeout;  //定时任务的超时时间
    bool _canceled;     //false-表示没有被取消， true-表示被取消
    TaskFunc _task_cb;  //定时器对象要执行的定时任务。
    ReleaseFunc _release; //拥有删除TimerWheel中保持的定时器对象信息
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb)
    _id(id),_timeout(delay),_task_cb(cb),_canceled(false){
    }
    ~TimerTask(){
        if(_canceled == false) _task_cb();
        _release();
    }
    void Cancel() { _canceled = true; }
    void SetRelease( const ReleaseFunc &cb) { _release = cb; }
    uint32_t DelayTime() { return _timeout; }
};

class TimerWheel{
private:
    using WeakTask = std::weak_ptr<TimerTask>
    using PtrTask = std::shard_ptr<TimerTask>
    int _tick; //当前的秒钟
    
    int _capacity; //表盘最⼤数量--其实就是最⼤延迟时间
    std::vector<std::vector<PtrTask>> _wheel; //时间轮or时间轴
    std::unordered_map<uint64_t,WeakTask> _timers;  //id和时间任务对象的映射

    EventLoop *_loop;
    int _timerfd; //定时器描述符——可读事件回调就是读取计数器，执行定时任务
    std::uinqur_ptr<Channel> _timer_channel;  //_timer_channel:定时器是事件
private:
    void RemoveTimer(uint64_t id){
        auto it = _timers.find(id);
        if(it != _timers.end()){
            _timers.erase(it);
        }
    }

    static int CreateTimerfd(){
        int timerfd = timerfd_create(CLOCK_MONOTONIC,0); //创建
        if(timerfd < 0){
            lg(Error,"TIMERFD CREATE FAILED!");
            abort();
        }
        struct itimerspec itime;
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;//第一次超时事件为1s后
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv.sec = 0;//
        timerfd_settime(timefd,0,&itime,NULL);
        return timefd;
    }
    int ReadTimefd(){
        uint64_t times;
        int ret = read(_timerfd, &times, 8);
        if(ret<0){
            lg(Error,"READ TIMEFD FAILED!");
            abort();
        }
        return times;
    }
    void RunTimerTask(){
        _tick = (_tick + 1)%_capacity;//
        _wheel[_tick].clear();
    }
    void OnTimer(){
        int times = ReadTimefd();//读取实际的超时次数
        for(int i=0;i<times;i++){
            RunTimerTask();
        }
    }
    void TimerAddInloop(uint64_t id,uint32_t delay ,const TaskFunc& cb){
        PtrTask pt(new TimerTask(id,delay,cb));//创建定时任务
        pt->setRealease(std::bind(&TimerWheel::RemoveTimer,this,id));//定时任务设置从wheel上erase的函数
        int pos = (_tick + delay) % _capacity;//时间轮挂载时间任务
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }
    void TimerRefreshInLoop(uint64_t id){
        auto it = _timers.find(id);
        if(it == _timers.end()){
            return ; //没找到定时任务，没法刷新，没法延迟
        }
        PtrTask pt = it->second.lock();//
        int delay = pt->DelayTime();
        int pos = (delay+_tick) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void TimerCancelInLoop(uint64_t id){
        auto it = _timerfd.find(id);
        if(it == _timers.end()){
            return ;
        }
        PtrTask pt = it.second.lock();
        if(pt) pt->Cancel();
    }
public:
    TimerWheel(EventLoop *loop):_capacity(60), _tick(0),_wheel(_capacity),_loop(loop),
    _timerfd(CreateTimerfd()),_timer_channel(new Channel(_loop,_timerfd)){ //_timefd:
        _timer_channel -> SetReadCallback(std::bind(&TimerWheel::OnTime,this));//
        _timer_channel -> EnabelRead();      //启动时间监控
    }
    void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb);
    void TimerRefresh(uint64_t id);
    void TimerCancel(uint64_t id);
    bool HasTimer(uint64_t id){
        auto it = _timers.find(id);
        if( it == _timers.end()){
            return false;
        }
        return true;
    } 
};

void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop,this,id,delay,cb));
}
// 刷新/延迟定时任务
void TimerWheel::TimerRefresh(uint64_t id){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop,this,id));
}
void TimerWheel::TimerCancel(uint64_t id){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop,this,id));
}